﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Web.UI;
using TallComponents.Web.Pdf.Resources;
using System.Web;
using System.ComponentModel;

[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ScriptResourcePath, "text/javascript")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageBusyPath, "image/gif")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageToolbarPath, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageSpacerPath, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageHoverPath, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageActivePath, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageClosePath, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageNextPath, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageOpenPath, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImagePageLayoutSingle, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImagePageLayoutDouble, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImagePageLayoutContinuous, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImagePageLayoutContinuousDouble, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImagePanPath, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImagePrevPath, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageZoom1On1Path, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageZoomInPath, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageZoomOutPath, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageZoomToPagePath, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageZoomToWidthPath, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageSearch, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageStop, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageRotateClockWise, "image/png")]
[assembly: WebResource(TallComponents.Web.Pdf.PdfViewerToolbar.ImageRotateCounterClockWise, "image/png")]

namespace TallComponents.Web.Pdf
{
    /// <summary>
    /// Toolbar for <see cref="PdfViewer"/>.
    /// </summary>
    /// <remarks>
    /// <see cref="PdfViewerToolbar"/> is an AJAX enabled control that can interact with a <see cref="PdfViewer"/>. 
    /// It provides feedback about the current page, the total number of pages and status of the viewer and allows users to browse from
    /// one page to the next, switch cursor mode (pan, zoom-in, zoom-out) and select fixed zoom factors or choose dynamic zoom settings
    /// (fit to width, fit to page and 1:1).
    /// <para>The toolbar can be customized to a certain extent. If you need a radically different look or behaviour, please consider
    /// implementing a custom toolbar. The developer guide for this product provides more information on how to do this.</para>
    /// <para>The toolbar may be customized by providing custom images for the buttons, the state overlays and the toolbar background.
    /// All toolbar images are assumed to be 24x24 pixels transparent images (both gif and png images are suitable). 
    /// The default spacer image is 8 pixels wide and 24 pixels high. The toolbar background should be at least 24 pixels high. This image will 
    /// be placed at the top left of the toolbar area and repeated horizontally to fill the entire width of the toolbar, any overflow will be cropped.</para>
    /// <para>Button state overlays can also be customized. There are four button states; disabled, normal, hover and selected. The disabled
    /// state is created using css opacity and cannot be customized. The hover and selected states may be customized through the <see cref="M:SelectedButtonImageUrl"/> and
    /// <see cref="M:HoverButtonImageUrl"/> properties. These button states are created by inserting an image below the toolbar button image.
    /// </para>
    /// </remarks>
    [System.Drawing.ToolboxBitmap(typeof(PdfViewerToolbar), IconPath)]
    [ToolboxItem("System.Web.UI.Design.WebControlToolboxItem, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
    public class PdfViewerToolbar : ScriptControl
    {
        // Note that resource paths always start with the assembly default namespace
        // JavaScript source file
#if DEBUG
        internal const string ScriptResourcePath = "TallComponents.Web.Pdf.PdfViewerToolbar.js";
#else
      internal const string ScriptResourcePath = "TallComponents.Web.Pdf.PdfViewerToolbar.min.js";
#endif
        internal const string IconPath = "TallComponents.Web.Pdf.PdfWebViewer.ico";
        // Default images
        internal const string ImageBusyPath = "TallComponents.Web.Pdf.busy.gif";
        internal const string ImageToolbarPath = "TallComponents.Web.Pdf.toolbar.default.toolbar.png";
        internal const string ImageSpacerPath = "TallComponents.Web.Pdf.toolbar.default.spacer.png";
        internal const string ImageHoverPath = "TallComponents.Web.Pdf.toolbar.default.hover.png";
        internal const string ImageActivePath = "TallComponents.Web.Pdf.toolbar.default.active.png";
        internal const string ImageClosePath = "TallComponents.Web.Pdf.toolbar.default.close.png";
        internal const string ImageNextPath = "TallComponents.Web.Pdf.toolbar.default.next.png";
        internal const string ImageOpenPath = "TallComponents.Web.Pdf.toolbar.default.open.png";
        internal const string ImagePageLayoutSingle = "TallComponents.Web.Pdf.toolbar.default.pageLayoutSingle.png";
        internal const string ImagePageLayoutDouble = "TallComponents.Web.Pdf.toolbar.default.pageLayoutDouble.png";
        internal const string ImagePageLayoutContinuous = "TallComponents.Web.Pdf.toolbar.default.pageLayoutContinuous.png";
        internal const string ImagePageLayoutContinuousDouble = "TallComponents.Web.Pdf.toolbar.default.pageLayoutContinuousDouble.png";
        internal const string ImagePanPath = "TallComponents.Web.Pdf.toolbar.default.pan.png";
        internal const string ImagePrevPath = "TallComponents.Web.Pdf.toolbar.default.prev.png";
        internal const string ImageZoom1On1Path = "TallComponents.Web.Pdf.toolbar.default.zoom1on1.png";
        internal const string ImageZoomInPath = "TallComponents.Web.Pdf.toolbar.default.zoomIn.png";
        internal const string ImageZoomOutPath = "TallComponents.Web.Pdf.toolbar.default.zoomOut.png";
        internal const string ImageZoomToPagePath = "TallComponents.Web.Pdf.toolbar.default.zoomToPage.png";
        internal const string ImageZoomToWidthPath = "TallComponents.Web.Pdf.toolbar.default.zoomToWidth.png";
        internal const string ImageSearch = "TallComponents.Web.Pdf.toolbar.default.search.png";
        internal const string ImageStop = "TallComponents.Web.Pdf.toolbar.default.stop.png";
        internal const string ImageRotateClockWise = "TallComponents.Web.Pdf.toolbar.default.rotate_cw.png";
        internal const string ImageRotateCounterClockWise = "TallComponents.Web.Pdf.toolbar.default.rotate_ccw.png";

        internal const string ClientControlType = "TallComponents.PdfViewerToolbar";

        /// <summary>
        /// Gets or sets the control ID of the PdfViewer this toolbar will interact with.
        /// </summary>
        /// <value>The control ID of the PdfViewer this toolbar will interact with.</value>
        [IDReferenceProperty(typeof(PdfViewer))]
        public string PdfViewerControlId { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the toolbar button that navigates to the previous page.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the toolbar button that navigates to the previous page.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string PreviousImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the toolbar button that navigates to the next page.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the toolbar button that navigates to the next page.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string NextImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed in the toolbar when the viewer is busy.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.
        /// <para>This image should be an animated gif.</para></remarks>
        /// <value>The URL of the image displayed in the toolbar when the viewer is busy.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string BusyImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the toolbar button that shows the open file dialog.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the toolbar button that shows the open file dialog.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string OpenImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the toolbar button that closes the current file.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the toolbar button that closes the current file.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string CloseImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the toolbar button that switches the viewer to pan mode.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the toolbar button that switches the viewer to pan mode.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string PanImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the toolbar button that switches the viewer to page layout single.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the toolbar button that switches the viewer to page layout single.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string SinglePageLayoutImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the toolbar button that switches the viewer to page layout double.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the toolbar button that switches the viewer to page layout double.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string DoublePageLayoutImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the toolbar button that switches the viewer to page layout continuous.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the toolbar button that switches the viewer to page layout continuous.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string ContinuousPageLayoutImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the toolbar button that switches the viewer to page layout continuous double.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the toolbar button that switches the viewer to page layout continuous double.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string ContinuousDoublePageLayoutImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the toolbar button that switches the viewer to zoom-in mode.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the toolbar button that switches the viewer to zoom-in mode.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string ZoomInImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the toolbar button that switches the viewer to zoom-out mode.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the toolbar button that switches the viewer to zoom-out mode.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string ZoomOutImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the zoom-to-width toolbar button.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the zoom-to-width toolbar button.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string ZoomToWidthImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the zoom-to-page toolbar button.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The the URL of the image displayed on the zoom-to-page toolbar button.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string ZoomToPageImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the zoom 1:1 toolbar button.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the zoom 1:1 toolbar button.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string Zoom1On1ImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the search button.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the search toolbar button.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string SearchImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the search cancel button.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the search cancel toolbar button.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string SearchCancelImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the rotate clockwise button.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the rotate clockwise toolbar button.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string RotateClockwiseImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image displayed on the rotate counter clockwise button.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The URL of the image displayed on the rotate counter clockwise toolbar button.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string RotateCounterClockwiseImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image used to render the toobar background.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The background image URL.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string ToolbarBackgroundImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image used to render the selected state of a toolbar button.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The active background image URL.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string SelectedButtonImageUrl { get; set; }

        /// <summary>
        /// Gets or sets URL of the image used to render the hover state of a toobar button.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The hover background image URL.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string HoverButtonImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the URL of the image used to render a spacer between button groups.
        /// </summary>
        /// <remarks>If no value is specified the toolbar will use a default image.</remarks>
        /// <value>The spacer image URL.</value>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
           typeof(System.Drawing.Design.UITypeEditor))]
        [UrlProperty]
        public string SpacerImageUrl { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether to show file buttons (open and close).
        /// </summary>
        /// <value><c>true</c> to show file buttons (open and close); otherwise, <c>false</c>. Default is false.</value>
        [DefaultValue(false)]
        public bool ShowFileButtons { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether to show the search box.
        /// </summary>
        /// <value><c>true</c> to show the search box; otherwise, <c>false</c>.</value>
        [DefaultValue(false)]
        public bool ShowSearchBox { get; set; }

        /// <summary>
        /// Invoked during the PreRendering stage to finalize the control for rendering.
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        /// <exception cref="InvalidOperationException"></exception>
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            if (Page.Header == null)
                throw new InvalidOperationException(Text.Toolbar_Head_control_required);

            var toolbarButtonStyle = new CssStyle();
            toolbarButtonStyle.Add("margin-right", "3px");
            toolbarButtonStyle.Add("width", "auto");
            toolbarButtonStyle.Add("float", "left");
            toolbarButtonStyle.Add("display", "inline-block");
            Page.Header.StyleSheet.CreateStyleRule(toolbarButtonStyle, this, ".pdftbItem");

            var toolbarButtonNoBorder = new CssStyle();
            toolbarButtonNoBorder.Add("border", "none");
            Page.Header.StyleSheet.CreateStyleRule(toolbarButtonNoBorder, this, ".pdftbItem img");

            var toolbarButtonFireFoxFix = new CssStyle();
            toolbarButtonFireFoxFix.Add("display", "inline-block");
            Page.Header.StyleSheet.CreateStyleRule(toolbarButtonFireFoxFix, this, ".pdftbItem a");

            var toolbarDisabledStyle = new CssStyle();
            toolbarDisabledStyle.Add("cursor", "default");
            toolbarDisabledStyle.Add("background", "transparent !important");
            Page.Header.StyleSheet.CreateStyleRule(toolbarDisabledStyle, this, ".pdftbDisabled");

            var toolbarDisabledStyle2 = new CssStyle();
            toolbarDisabledStyle2.Add("-ms-filter", "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)");
            toolbarDisabledStyle2.Add("filter", "alpha(opacity=40)");
            toolbarDisabledStyle2.Add("opacity", "0.4");
            Page.Header.StyleSheet.CreateStyleRule(toolbarDisabledStyle2, this, ".pdftbDisabled img");

            var toolbarSpacerStyle = new CssStyle();
            toolbarSpacerStyle.Add("margin-right", "3px");
            toolbarSpacerStyle.Add("width", "8px");
            toolbarSpacerStyle.Add("height", "24px");
            toolbarSpacerStyle.Add("float", "left");
            Page.Header.StyleSheet.CreateStyleRule(toolbarSpacerStyle, this, ".pdftbSpacer");

            var hoverStyle = new CssStyle();
            hoverStyle.Add("background", string.Format("transparent url({0}) no-repeat scroll top left",
               string.IsNullOrEmpty(HoverButtonImageUrl)
                     ? Page.ClientScript.GetWebResourceUrl(typeof(PdfViewerToolbar), ImageHoverPath)
                     : ResolveClientUrl(HoverButtonImageUrl)));
            Page.Header.StyleSheet.CreateStyleRule(hoverStyle, this, string.Format("#{0} a:hover", ClientID));

            var activeStyle = new CssStyle();
            activeStyle.Add("background", string.Format("transparent url({0}) no-repeat scroll top left",
               string.IsNullOrEmpty(SelectedButtonImageUrl)
                     ? Page.ClientScript.GetWebResourceUrl(typeof(PdfViewerToolbar), ImageActivePath)
                     : ResolveClientUrl(SelectedButtonImageUrl)));
            Page.Header.StyleSheet.CreateStyleRule(activeStyle, this, ".pdftbActive");

            var linkOverrideStyle = new CssStyle();
            linkOverrideStyle.Add("outline", "0px none black");
            linkOverrideStyle.Add("-moz-outline", "0px none");
            Page.Header.StyleSheet.CreateStyleRule(linkOverrideStyle, this, string.Format("#{0} a", ClientID));

            if (string.IsNullOrEmpty(PdfViewerControlId))
                throw new InvalidOperationException(Text.PdfViewerControlId_not_set);

            var targetControl = FindTargetControl(PdfViewerControlId) as PdfViewer;

            if (null == targetControl)
                throw new InvalidOperationException(string.Format(Text.ViewerControl_not_found, PdfViewerControlId));

            _pageViewChildControlId = targetControl.ClientID;
        }

        /// <summary>
        /// Renders the control to the specified HTML writer.
        /// </summary>
        /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the control content.</param>
        protected override void Render(HtmlTextWriter writer)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Id, ClientID);

            if (!string.IsNullOrEmpty(CssClass))
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass);
            }

            if (ControlStyleCreated && !BorderColor.IsEmpty && !BorderWidth.IsEmpty &&
                    (BorderStyle != System.Web.UI.WebControls.BorderStyle.None && BorderStyle != System.Web.UI.WebControls.BorderStyle.NotSet))
            {
                var border = string.Format("{0} {1} {2}",
                                            BorderWidth.ToString(CultureInfo.InvariantCulture), BorderStyle,
                                            System.Drawing.ColorTranslator.ToHtml(BorderColor).ToLowerInvariant());
                writer.AddStyleAttribute("border", border);
            }

            bool useDefaultStyles = string.IsNullOrEmpty(CssClass);

            if (!Width.IsEmpty || useDefaultStyles)
                writer.AddStyleAttribute(HtmlTextWriterStyle.Width, Width.IsEmpty ? "inherit" : Width.ToString(CultureInfo.InvariantCulture));

            if (!Height.IsEmpty || useDefaultStyles)
                writer.AddStyleAttribute(HtmlTextWriterStyle.Height, Height.IsEmpty ? "24px" : Height.ToString(CultureInfo.InvariantCulture));

            if (useDefaultStyles || (ControlStyleCreated && !ControlStyle.Font.Size.IsEmpty))
            {
                writer.AddStyleAttribute(HtmlTextWriterStyle.FontSize,
                                          ControlStyle.Font.Size.IsEmpty ? "14px" : ControlStyle.Font.Size.ToString(CultureInfo.InvariantCulture));
            }
            // Background CSS
            if (useDefaultStyles || (ControlStyleCreated && (!string.IsNullOrEmpty(ToolbarBackgroundImageUrl) || !BackColor.IsEmpty)))
            {
                if (!BackColor.IsEmpty)
                {
                    writer.AddStyleAttribute("background-color", System.Drawing.ColorTranslator.ToHtml(BackColor));
                }
                else if (useDefaultStyles || !string.IsNullOrEmpty(ToolbarBackgroundImageUrl))
                {
                    writer.AddStyleAttribute("background", string.Format("transparent url({0}) repeat-x scroll top left",
                       string.IsNullOrEmpty(ToolbarBackgroundImageUrl)
                       ? Page.ClientScript.GetWebResourceUrl(typeof(PdfViewerToolbar), ImageToolbarPath)
                       : ResolveClientUrl(ToolbarBackgroundImageUrl)));
                }
            }

            if (useDefaultStyles)
            {
                writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingTop, "0px");
                writer.AddStyleAttribute(HtmlTextWriterStyle.Position, "relative");
            }

            writer.RenderBeginTag(HtmlTextWriterTag.Div);
            writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingLeft, "5px");
            writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingRight, "5px");
            if (!DesignMode)
            {
                writer.RenderBeginTag(HtmlTextWriterTag.Div); // inner div to add padding
                if (ShowFileButtons)
                {
                    RenderButton(writer, "open", OpenImageUrl, ImageOpenPath, Text.Toolbar_Open);
                    RenderButton(writer, "close", CloseImageUrl, ImageClosePath, Text.Toolbar_Close);
                    RenderSpacer(writer);
                }
                RenderButton(writer, "prev", PreviousImageUrl, ImagePrevPath, Text.Toolbar_Previous_Page);

                writer.Write("<div id=\"pageNumber\" class=\"pdftbItem\" style=\"margin-top: 2px;\"> </div> ");

                RenderButton(writer, "next", NextImageUrl, ImageNextPath, Text.Toolbar_Next_Page);

                RenderSpacer(writer);
                writer.Write("<div class=\"pdftbItem\" style=\"margin-top: 1px;\">");
                writer.Write("<select class=\"zoomSelect\" style=\"margin: 0px; visibility: hidden;\">" +
                              "<option value=\"1.5\">150%</option>" +
                              "<option value=\"1\">100%</option>" +
                              "<option value=\"0.75\">75%</option>" +
                              "<option value=\"0.5\">50%</option>" +
                              "<option disabled=\"disabled\"></option>" +
                              "<option value=\"page\">" + Text.Toolbar_ZoomOption_FitToPage + "</option>" +
                              "<option value=\"width\">" + Text.Toolbar_ZoomOption_FitToWidth + "</option>" +
                              "</select>");
                writer.Write("</div> ");
                RenderButton(writer, "pan", PanImageUrl, ImagePanPath, Text.Toolbar_Pan);
                RenderButton(writer, "zoomOut", ZoomOutImageUrl, ImageZoomOutPath, Text.Toolbar_ZoomOut);
                RenderButton(writer, "zoomIn", ZoomInImageUrl, ImageZoomInPath, Text.Toolbar_ZoomIn);
                RenderSpacer(writer);
                RenderButton(writer, "zoom1on1", Zoom1On1ImageUrl, ImageZoom1On1Path, Text.Toolbar_Zoom1On1);
                RenderButton(writer, "zoomToPage", ZoomToPageImageUrl, ImageZoomToPagePath, Text.Toolbar_ZoomToPage);
                RenderButton(writer, "zoomToWidth", ZoomToWidthImageUrl, ImageZoomToWidthPath, Text.Toolbar_ZoomToWidth);
                RenderSpacer(writer);
                RenderButton(writer, "pageLayoutSingle", SinglePageLayoutImageUrl, ImagePageLayoutSingle, Text.Toolbar_SinglePageLayout);
                RenderButton(writer, "pageLayoutDouble", DoublePageLayoutImageUrl, ImagePageLayoutDouble, Text.Toolbar_DoublePageLayout);
                RenderButton(writer, "pageLayoutContinuous", ContinuousPageLayoutImageUrl, ImagePageLayoutContinuous, Text.Toolbar_ContinuousPageLayout);
                RenderButton(writer, "pageLayoutContinuousDouble", ContinuousDoublePageLayoutImageUrl, ImagePageLayoutContinuousDouble, Text.Toolbar_ContinuousDoublePageLayout);
                RenderSpacer(writer);
                RenderButton(writer, "rotateCounterClockwise", RotateCounterClockwiseImageUrl, ImageRotateCounterClockWise, Text.Toolbar_RotateCounterClockwise);
                RenderButton(writer, "rotateClockwise", RotateClockwiseImageUrl, ImageRotateClockWise, Text.Toolbar_RotateClockwise);
                if (ShowSearchBox)
                {
                    RenderSpacer(writer);
                    writer.Write("<div class=\"pdftbItem\" style=\"margin-top: 1px;\">");
                    writer.Write("<input type=\"text\" class=\"searchBox\" />");
                    writer.Write("</div> ");
                    RenderButton(writer, "search", SearchImageUrl, ImageSearch, Text.Toolbar_Search);
                    RenderButton(writer, "searchCancel", SearchCancelImageUrl, ImageStop, Text.Toolbar_Cancel);
                }

                writer.Write(
                   "<img id=\"busy\" src=\"{0}\" style=\"position: absolute; right: 2px; top: 2px; visibility: hidden;\" />",
                   string.IsNullOrEmpty(BusyImageUrl)
                      ? HttpUtility.HtmlAttributeEncode(Page.ClientScript.GetWebResourceUrl(typeof(PdfViewerToolbar),
                                                                                              ImageBusyPath))
                      : ResolveClientUrl(BusyImageUrl));
                writer.RenderEndTag(); // inner div
            }
            writer.RenderEndTag(); // div

            if (!DesignMode)
            {
                ScriptManager.RegisterScriptDescriptors(this);
            }
        }

        private void RenderSpacer(HtmlTextWriter writer)
        {
            writer.Write("<div class=\"pdftbSpacer\"><img src=\"{0}\" /></div>", string.IsNullOrEmpty(SpacerImageUrl)
                  ? HttpUtility.HtmlAttributeEncode(Page.ClientScript.GetWebResourceUrl(typeof(PdfViewerToolbar), ImageSpacerPath))
                  : ResolveClientUrl(SpacerImageUrl));
        }

        private void RenderButton(HtmlTextWriter writer, string key, string imageUrl, string resourceId, string tooltip)
        {
            writer.Write("<div class=\"pdftbItem\">");
            writer.Write("<a href=\"#\" id=\"{0}\" class=\"pdftbDisabled\" title=\"{2}\"><img src=\"{1}\" alt=\"{2}\"/></a>", key,
               string.IsNullOrEmpty(imageUrl)
                  ? HttpUtility.HtmlAttributeEncode(Page.ClientScript.GetWebResourceUrl(typeof(PdfViewerToolbar), resourceId))
                  : ResolveClientUrl(imageUrl),
               HttpUtility.HtmlAttributeEncode(tooltip));
            writer.Write("</div> ");
        }

        /// <summary>
        /// Searches the control hierarchy to locate the named control.
        /// </summary>
        /// <param name="id">The control id of the control to look for.</param>
        /// <returns>The control with the specified <paramref name="id"/> or <c>null</c> if no matching control is found.</returns>
        /// /// <exception cref="ArgumentException">Occures when <paramref name="id"/> is <c>null</c> or empty.</exception>
        protected Control FindTargetControl(string id)
        {
            if (string.IsNullOrEmpty("id"))
                throw new ArgumentException("id");

            Control ctrl = base.FindControl(id);
            Control namingContainer = NamingContainer;

            // Walk up into the control tree to locate the target control
            while ((null == ctrl) && (null != namingContainer))
            {
                ctrl = namingContainer.FindControl(id);
                namingContainer = namingContainer.NamingContainer;
            }

            return ctrl;
        }

        /// <summary>
        /// Gets the script manager for the current request.
        /// </summary>
        /// <value>The script manager for the current request.</value>
        private ScriptManager ScriptManager
        {
            get
            {
                if (_scriptManager == null)
                {
                    if (Page == null)
                    {
                        throw new InvalidOperationException(Text.Common_PageCannotBeNull);
                    }
                    _scriptManager = ScriptManager.GetCurrent(Page);
                    if (_scriptManager == null)
                    {
                        throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, Text.Common_ScriptManagerRequired, ID));
                    }
                }
                return _scriptManager;
            }
        }


        /// <summary>
        /// Returns the <see cref="T:System.Web.UI.ScriptDescriptor"/> objects for the control.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Collections.IEnumerable"/> collection of <see cref="T:System.Web.UI.ScriptDescriptor"/> objects.
        /// </returns>
        protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
        {
            var desc = new ScriptControlDescriptor(ClientControlType, ClientID);
            desc.AddProperty("targetControlId", _pageViewChildControlId);
            yield return desc;
        }

        /// <summary>
        /// Returns the script files for the control.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Collections.IEnumerable"/> collection that contains ECMAScript (JavaScript) files that have been registered as embedded resources.
        /// </returns>
        protected override IEnumerable<ScriptReference> GetScriptReferences()
        {
            var scriptReferences = new List<ScriptReference> {
            new ScriptReference( ScriptResourcePath, "TallComponents.Web.PdfViewer" )
         };
            return scriptReferences;
        }

        private string _pageViewChildControlId;
        private ScriptManager _scriptManager;
    }
}
